use chacha20::{
    cipher::{NewCipher, StreamCipher},
    XChaCha20,
};

use crate::key::Key32;
use crate::nonce::Nonce24;
use std::{
    fs::File,
    io::{BufReader, BufWriter, Error, Read, Write},
};

const BUFF_SIZE: usize = 4096;

pub fn xchacha20_file_enc<R: Read, W: Write>(
    input: &mut R,
    key: &Key32,
    nonce: &Nonce24,
    out: &mut W,
) -> Result<(), Box<Error>> {
    let mut cipher = XChaCha20::new(key, nonce);
    let mut buf = [0u8; BUFF_SIZE];
    out.write_all(nonce)?;
    while let Ok(n) = input.read(&mut buf) {
        println!("read {}", n);
        if n == 0 {
            break;
        }
        cipher.apply_keystream(buf[..n].as_mut());
        out.write_all(&buf[..n])?;
    }
    Ok(())
}

pub fn xchacha20_file_dec<R: Read, W: Write>(
    input: &mut R,
    key: &Key32,
    out: &mut W,
) -> Result<(), Box<Error>> {
    let mut nonce = Nonce24::default();
    input.read_exact(nonce.as_mut())?;
    let mut buf = [0u8; BUFF_SIZE];
    let mut cipher = XChaCha20::new(key, &nonce);
    while let Ok(n) = input.read(&mut buf) {
        if n == 0 {
            break;
        }
        cipher.apply_keystream(buf[..n].as_mut());
        out.write_all(&buf[..n])?;
    }
    Ok(())
}
